;;Projeto de Paradigmas de Programação
;;3 quadrimestre de 2013
;;Autores: Eduardo Pinhata, José João de Moura

;;O presente código foi modificado de um exemplo de código de jogo mud que utiliza hash-tables.
;;a licença é dada abaixo.

;;#lang scheme

;; License: MIT License
;; Author: majid khosravi
;; Website: http://www.majidkhosravi.com


(require 'srfi-69 'srfi-1 'srfi-13 'tcp 'srfi-18)
;; lista de associacao da descricao das salas
(define descriptions '( (1 "Voce esta na floresta oeste, Direcoes permitidas sao 'Norte' e 'Leste'")
                        (2 "Floresta, Direcoes premitidas sao 'Oeste' e 'Leste'")
                        (3 "Floresta leste, Voce pode ver uma casa a Leste, Direcoes permitidas sao 'Oeste', 'Norte' e 'Leste'")
                        (4 "Voce esta em uma casa, Ha uma porta para 'Oeste'")
                        (5 "Caminho do rio, Ha um caminho para a floresta no 'Sul' e uma casa pode ser vista no 'Norte'")
                        (6 "Voce esta em uma casa, Ha uma porta para o 'Norte'")
                        (7 "Estrada da montanha, A floresta esta ao 'Sul' e a Montanha esta ao 'Norte'")
                        (8 "Voce esta em uma casa, Ha uma porta para o 'Norte'")
                        (9 "Voce esta em uma casa, Ha uma porta para o 'Sul'")
                        (10 "Rio ao sul, Ha um caminho para o 'Norte' e uma casa no 'Sul'")
                        (11 "Montanha, Ha um caminho para o 'Norte' e uma estrada no 'Sul'")
                        (12 "Estrada Leste, Ha uma estrada para o 'Norte e uma casa no 'Sul' ")
                        (13 "Voce esta em uma casa, Ha uma porta para o 'Norte'")
                        (14 "Rio Norte, Ha um caminho ara o 'Norte' e uma estrada para o 'Sul'")
                        (15 "Estrada do Deserto, Montanhas estao ao 'Sul' e ha uma estrada para o 'Leste'")
                        (16 "Cabana Leste, A montanha esta a 'Oeste', ha uma estrada ao 'Sul' e uma caverna com uma porta ao 'Norte'")
                        (17 "Entrada do Castelo, Há uma porta ao 'Norte' e o fim da estada ao 'Sul', ha um tunel a 'Leste'")
                        (18 "Estrada do tunel, Ha um caminho para o 'Sul' e 'Oeste', O tunel esta a 'Leste'")
                        (19 "Tunel, A porta da caverna esta a 'Leste' e ha um caminho para 'Oeste'")
                        (20 "Caverna, Ha um tunel para 'Oeste'")
                        (21 "Quintal do Castelo, Ha uma porta para fora localizada a 'Oeste' e a uma porta para 'Leste'")
                        (22 "Corredor principal do Castelo, Ha um porta para o quintal do castelo a 'Oeste' e uma porta a 'Leste'")
                        (23 "Hall do Castelo, O corredor principal esta a 'Oeste' e a prisao esta para 'Leste'")
                        (24 "Prisao, Voce achou a rainha e resgatou-a!!!")))

;; direcoes das salas
(define directions '( (1 (norte 5) (sul 0) (oeste 0) (leste 2))
                      (2 (norte 0) (sul 0) (oeste 1) (leste 3))
                      (3 (norte 7) (sul 0) (oeste 2) (leste 4))
                      (4 (norte 0) (sul 0) (oeste 3) (leste 0))
                      (5 (norte 9) (sul 1) (oeste 0) (leste 0))
                      (6 (norte 10) (sul 0) (oeste 0) (leste 0))
                      (7 (norte 11) (sul 3) (oeste 0) (leste 0))
                      (8 (norte 12) (sul 0) (oeste 0) (leste 0))
                      (9 (norte 0) (sul 5) (oeste 0) (leste 0))
                      (10 (norte 14) (sul 6) (oeste 0) (leste 0))
                      (11 (norte 15) (sul 7) (oeste 0) (leste 0))
                      (12 (norte 16) (sul 8) (oeste 0) (leste 0))
                      (13 (norte 17) (sul 0) (oeste 0) (leste 0))
                      (14 (norte 18) (sul 10) (oeste 0) (leste 0))
                      (15 (norte 0) (sul 11) (oeste 0) (leste 16))
                      (16 (norte 20) (sul 12) (oeste 15) (leste 0))
                      (17 (norte 21) (sul 13) (oeste 0) (leste 18))
                      (18 (norte 0) (sul 14) (oeste 17) (leste 19))
                      (19 (norte 0) (sul 0) (oeste 18) (leste 20))
                      (20 (norte 0) (sul 16) (oeste 19) (leste 0))
                      (21 (norte 0) (sul 17) (oeste 0) (leste 22))
                      (22 (norte 0) (sul 0) (oeste 21) (leste 23))
                      (23 (norte 0) (sul 0) (oeste 22) (leste 24))
                      (24 (norte 0) (sul 0) (oeste 23) (leste 0))))

;; propriedades das salas
(define rooms-list '( (1 (trancado #f) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (2 (trancado #f) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (3 (trancado #f) (chave #f) (adaga #f) (inimigo #t) (potion #f) (fim #f))
                   (4 (trancado #f) (chave #f) (adaga #f) (inimigo #f) (potion #t) (fim #f))
                   (5 (trancado #f) (chave #f) (adaga #t) (inimigo #f) (potion #f) (fim #f))
                   (6 (trancado #f) (chave #t) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (7 (trancado #t) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (8 (trancado #f) (chave #t) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (9 (trancado #f) (chave #t) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (10 (trancado #f) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (11 (trancado #f) (chave #f) (adaga #f) (inimigo #t) (potion #f) (fim #f))
                   (12 (trancado #f) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (13 (trancado #f) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (14 (trancado #f) (chave #f) (adaga #f) (inimigo #t) (potion #f) (fim #f))
                   (15 (trancado #f) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (16 (trancado #f) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (17 (trancado #f) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (18 (trancado #f) (chave #f) (adaga #f) (inimigo #t) (potion #f) (fim #f))
                   (19 (trancado #f) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (20 (trancado #t) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (21 (trancado #t) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (22 (trancado #f) (chave #f) (adaga #f) (inimigo #t) (potion #f) (fim #f))
                   (23 (trancado #f) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #f))
                   (24 (trancado #f) (chave #f) (adaga #f) (inimigo #f) (potion #f) (fim #t))))

; ler a lista de sala dentro da tabela de hash de salas
(define roomsdb (make-hash-table))

; iterar sobre todos os itens dentro da lista de salas e inserí-los dentro da tabela de hash
(for-each (lambda (x) 
            (hash-table-set! roomsdb (car x) (cdr x))) rooms-list)

; descricao dos itens das salas
(define game-texts '((bemvindo " --={ Bem-vndo a LGN (Lenda do Grande Ninja)  }=--\n --={ Voce precisa achar a rainha que estra trancada em um casteo para vencer o jogo!  }=--") 
                     (adaga "Ha uma 'Adaga' nesta sala, digite 'pegar' para pega-la!")
                     (no-adaga "Voce nao possui nenhuma adaga para lutar")
                     (trancado "Essa porta esta trancada, digite 'abrir' para abrir a porta")
                     (chave "Ha uma 'Chave' nessa sala, digite 'pegar' para pega-la")
                     (inimigo "Há um 'Inimigo' nessa sala, digite 'lutar' para lutar com o inimigo")
                     (potion "Ha uma 'Pocao de cura' nessa sala, digite 'coletar' para coleta-la")
                     (inimigo-semadaga "Voce nao tem uma adaga para lutar contra o inimigo")
                     (sem-chave "Voce nao tem nenhuma chave para abrir essa sala")
                     (abrir-tranca "Voce usou sua chave e essa sala agora esta aberta")
                     (pegar "Voce pegou uma chave nessa sala")
                     (erro-pegar "Nao ha nenhuma chave nessa sala para ser pega")
                     (pegar-adaga "Voce pegou uma adaga nessa sala")
                     (erro-pegar-adaga "Nao ha nenhuma adaga nessa sala")
                     (lutar "Voce derrotou o inimigo")
                     (erro-lutar  "Nao ha nenhum inimigo para lutar")
                     (coletar "Voce coletou uma pocao de cura nessa sala.")
                     (erro-coletar "Nao ha nenhuma pocao de cura para ser coletada.")
                     (abrir "Voce usou uma chave para abrir a porta")
                     (erro-abrir "Essa porta nao esta trancada")
                     (curar-no-potion "Voce nao tem nenhuma pocao para se curar")
                     (curar "Voce se curou, sua vida voltou a ser 100")
                     (vida-cheia "Sua vida esta 100%, nao ha necessidade de se curar agora")
                     (alerta-inimigo "Voce deve matar o inimigo primeito")
                     (ataque-inimigo "O inimigo te atacou e voce perdeu 20% de sua vida")
                     (jogador-morreu "Voce esta morto!")
                     (voce-venceu "Voce venceu, voce chegou no seu destino")))

;;cria uma tablea de hash com os atributos do jogador
(define jogador (make-hash-table))
;;(hash-table-set! player 0 '(1 (keys 0)(dagger 0) (potion 0) (life 100)))

;;troca um item dentro de uma lista pelo valor dado
(define (replace-room-item list item new-value)
  (cond
    ((null? list) (quote())) ;se a lista for nula, retorna '()
    (else (cond
            ((eq? (caar list) item) ;se o caar da lista for igual ao item
             (cons new-value (cdr list))) ;usa cons no novo valor e o resto da lista
            (else (cons (car list) ;caso nao seja o item, junta o primeiro elemento com a chamada da funcao e o resto da lista
                        (replace-room-item (cdr list) item new-value))))))) 

;;atualiza os atributos de um jogador dado uma chave e o seu valor
;;pid - player id - numero usado para identificar o jogador na tabela jogador
;;o value precisa ser a lista associada, por exemplo (vida 100). Alterara a vida do jogador para 100
(define (player-update key value pid)
  (hash-table-set! jogador pid (cons '1 (replace-room-item  (cdr (hash-table-ref jogador pid)) key value))))

;; pega a lista de associacao de uma lista pelo id
(define (assq-ref assqlist id)
  (cdr (assq id assqlist)))

;; pega os atributos de um jogador dado uma determinada chave
;;por exemplo, se for colocado (player-attribute 'vida 0), ele mostrara quanto
;; o jogador 0 tem de vida. 
(define (player-attribute key pid)
  (car (assq-ref (cdr (hash-table-ref jogador pid)) key)))

;; acrescenta um valor aos atributos do jogador
;exemplo: (player0add0value 'vida 20 0) - acrescenta 20 na vida do jogador
(define (player-add-value key value pid)
  (let ((new-value (+ (player-attribute key pid) value)))
    (player-update key (list key new-value) pid)))

;;imprime os itens do jogador e todos os dados sao enviados para a saida out, que é passada mais abaixo
(define (player-status out pid)
  (let ((current-output-port out))
    (display (format "  ==[  ") out)
    (for-each (lambda (x) (display (format "~a: ~a  " (car x) (cadr x)) out) ) (cdr (hash-table-ref jogador pid))) ;;para cada item na lista cdr do jogador pid que esta na tbela de hash, ele os imprime na formatacao dada
    (write-line (format "]==") out) ))

;;recebe um atribudo de uma dada lista de associacao
;;entra dentro de uma lista de associação e recebe outra, entra nessa outra lista e recebe a informação
(define (lookup data room-id attribute)
  (car (assq-ref (assq-ref data room-id) attribute)))

;;recebe a descricao de uma sala dado um determinado rid (room id)
(define (get-room-description rid)
  (car (assq-ref descriptions rid)))

;; retorna a descricao de um item na tabela game-text e envia para a saida out
(define (describe item out)
  (let ((current-output-port out))
    (write-line (format "~a" (car (assq-ref game-texts item))) out)))

;;retorna as direcoes possiveis de se ir dado um rid especifico
(define (get-available-directions rid)
  (let ((direction (assq-ref directions rid)))
    (map car (filter (lambda (x) (> (second x) 0)) direction)))) ;;filtra todos os itens da tabela direction que tem o indice maior que 0

;;checa a tabela de hash roomsdb e retorna o valor de um atributo de roomsdb
;; checks roomsdb hash table and returns value of an attribute in the roomsdb
(define (get-room-item id field)
  (if (hash-table-exists? roomsdb id) ;existe a tabela com determinado id?
      (let ((record (hash-table-ref roomsdb id))) ;;se sim, define record como a tabela de hash id
        (if (memq field '(trancado chave adaga inimigo potion fim)) ;;se o field é membro das opcoes a seguir
          (cadr (assq field record)) ;;retorna o valor contigo no campo procurado
          "tipo errado de field"));;caso nao seja membro, retorna a frase
      "sala nao existe"));caso nao exista a sala com o id procurado

;; retorna as portas trancadas na sala dada
;;entra na tabela de direcoes e verifica se a sala que a direcao indica esta trancada ou não
;;para isso, entra das direcoes possiveis dentro da sala e retorna somente os valores que
;;tem true dentro de trancado
(define (get-locked-room rid)
  (filter 
   (lambda (x) (get-room-item x 'trancado)) 
   (map (lambda (x) (lookup directions rid x))  (get-available-directions rid))))

;retorna um comando dependendo do item que se encontra na sala
(define (map-item-command item)
  (if (eq? item 'trancado) ;;caso esteja trancado, retorna o comando abrir, a assim por diante
      'abrir
      (if (eq? item 'chave)
          'pegar
          (if (eq? item 'adaga)
              'pegar-adaga
              (if (eq? item 'potion)
                  'coletar
                  (when( eq? item 'inimigo)
                'lutar))))))

;; checa a tabela roomsdb e retorna a lista de um dado id de sala
(define (get-room id)
  (if (hash-table-exists? roomsdb id) ;;verifica se existe a tabela com o id dado
      (hash-table-ref roomsdb id) ;;retorna a lista com as propriedades das salas na tabela de hash roomsdb
      "sala nao existe")) ;caso não ache a sala, retorna a mensagem

;; retorna todos os itens disponiveis em uma dada sala com um determinado rid
(define (get-available-items rid)
  (let ((direction (get-room rid))) 
    (map car (filter (lambda (x) (eq? (second x) #t)) direction)))) ;;filtra e retorna o car de todos os elementos que tem o valor #t

; retorna a lista de comandos disponiveis dependendo dos atributos em roomsdb
(define (get-available-commands rid)
  (let ((l (map map-item-command (get-available-items rid)))) ;usa a funcao map-item-command em todos os itens obtidos com o get-available -items de um determinado rid
    (cons 'curar (if ( > (length (get-locked-room rid)) 0) ;disponibiliza o comando curar sempre e o comando abrir caso haja salas trancadas
                    (cons 'abrir l)        
                    l))))

;; imprime comandos disponiveis e as direcoes possiveis
;;essa funçao basicamente vai enviar ao jogador as direcoes que o mesmo pode seguir atraves
;;da funcao get-available-directions e os comandos que pode fazer com a funcao get-available-comandos
(define (print-available-commands rid out)
  (let ((current-output-port out))
    (display (format "========[  ") out)
    (for-each (lambda (x) (display (format "~a  " x) out)) (append (get-available-directions rid) (get-available-commands rid)))
    (write-line (format "]========") out)))

;; retorna todos os itens disponiveis em uma determinada sala de um determinado id
(define (get-available-items rid)
  (let ((direction (get-room rid))) 
    (map car (filter (lambda (x) (eq? (second x) #t)) direction)))) ; filtra todos os elementos que estao em uma sala que estejam setados como #t

;; processa um dado comando em uma dada sala, atualiza as tabelas de hash das salas se for necessario
(define (process-command cmd rid out pid)
  (let ((current-output-port out))
    (cond
     ;; abrir a porta
     ((equal? cmd 'abrir) ;se o comando for igual a abrir
      (if (> (length (get-locked-room rid)) 0) ;se a quantidade de portas trancadas for maior do que zero
          (if (> (player-attribute 'chaves pid) 0) ;se a quantidade de chaves que o jogador tiver for maior que zero
              (begin
                (let ((target-room (car (get-locked-room rid))))
                  (hash-table-set! roomsdb target-room (replace-room-item (get-room target-room) 'trancado '(trancado #f))) ;;altera o status de trancado da sala para destrancado
                  (player-add-value 'chaves -1 pid)
                  (describe 'abrir out)))
              (describe 'sem-chave out))
          (describe 'erro-abrir out)))

    ;; pegar uma chave em uma sala
     ((equal? cmd 'pegar) ;verifica se o comando é igual a pegar
      (if (get-room-item rid 'chave) ;;verifica se o quarto tem uma chave
          (begin
            (hash-table-set! roomsdb rid (replace-room-item (get-room rid) 'chave '(chave #f))) ;;altera o status de chave de #t para #f
            (player-add-value 'chaves 1 pid) ;adiciona uma chave no jogador
            (describe 'pegar out)) ;envia e mensagem de pegar cahve caso tenha a chave na sala
          (describe 'erro-pegar out))) ;envia a mensagem de erro ao pegar a chave caso não tenha chave na sala

    ;; pegar uma adaga na sala
     ((equal? cmd 'pegar-adaga) ;se o comando for igual a pegar-adaga
      (if (get-room-item rid 'adaga) ;;veriica se tem uma adaga na sala
          (begin
            (hash-table-set! roomsdb rid (replace-room-item (get-room rid) 'adaga '(adaga #f))) ;altera a condicao de haver adaga na sala
            (describe 'pegar-adaga out) ;envia  a mensagem de que a adaga foi pega
            (player-update 'adaga '(adaga 1) pid)) ;atualiza o numero de adagas do personagem
          (describe 'erro-pegar-adaga out))) ;;caso não tenha a adaga, envia a mensagem de erro

     ;;processo do comando de lutar
     ((equal? cmd 'lutar) ;caso o comando seja lutar
      (if (get-room-item rid 'inimigo) ;;veridica se há um inimigo na sala
          (begin
            (if (eq? (player-attribute 'adaga pid) 1) ;;verifica se o jogador possui uma adaga
                (begin
                  (hash-table-set! roomsdb rid (replace-room-item (get-room rid) 'inimigo '(inimigo #f))) ;caso tenha a adaga, remove o inimigo da sala
                  (describe 'lutar out)) ;envia mensagem de lutar
                (describe 'no-adaga out))) ;envia mensagem de que nao tem a adaga caso o jogador nao a tenha
          (describe 'erro-lutar out))) ;;caso nao tenha inimigo na sala, envia o erro de lutar

     ;;coletar a pocao de cura
     ((equal? cmd 'coletar) ;se o comando for coletar
      (if (get-room-item rid 'potion)  ;verifica se ha uma potion na sala
          (begin
            (hash-table-set! roomsdb rid (replace-room-item (get-room rid) 'potion '(potion #f))) ;caso tenha, altera o vaor de true para false para indicar que o jogador pegou a potion
            (player-add-value 'potion 1 pid) ;adiciona uma potion no inventario do jogador
            (describe 'coletar out)) ;envia a mensagem de coletar
          (describe 'erro-coletar out))) ;caso nao tenha a pocao, envia a mensagem de que nao ha pocao na sala

     ;;curar jogador
     ((equal? cmd 'curar) ;se o comando for curar, 
      (if (> (player-attribute 'potion pid) 0) ;verifica se o jogador possui uma potion
          (if(< (player-attribute 'vida pid) 100) ;;verifica se a vida do personagem esta menor do que a maxima
              (begin
                (player-add-value 'potion -1 pid) ;;atualiza o valor de potion do jogador
                (player-update 'vida '(vida 100) pid) ;;atualiza a vida do jogador do valor que estiver para 100
                (describe 'curar out)) ;envia a mensagem indicando que o jogador esta curad
              (describe 'vida-cheia out)) ;envia a mensagem indicando que o jogador esta com a vida cheia
          (describe 'curar-no-potion out))) ;envia mensagem dizendo que o jogador nao possui potion

    ;; selecao invalida
     (else
      (display (format "Comando invalido") out))))) ;;envia a mensagem de comando invalido caso nenhum dos comandos acima seja acionado

 
;;comaca o jogo de uma determinada sala
(define (startgame room-id in out pid)
  (let ((current-input-port in)
        (current-output-port out)
        (current-error-port out))
    (describe 'bemvindo out)

    ;;cria um jogador com a pid dada
    (hash-table-set! jogador pid '(1 (chaves 0)(adaga 0) (potion 0) (vida 100)))

    
    (let loop ((rid room-id) (echo #t)) ;define a rid como a room-id passada, ou seja a sala em que o personagem inicia o jogo
      (write-line (format "") out)

      ;; Qaundo um inimigo esta na sala
      (when (get-room-item rid 'inimigo); quando o valor de inimigo for #t
        (begin
          (describe 'ataque-inimigo out) ;envia mensagem informando que o inimigo atacou o jogar
          (player-add-value 'vida -20 pid))) ;decrementa 20 pontos da vida do jogador

    ;;imprime os itens e status do jogador
      (player-status out pid)

      ;;quando chega em u determinado destino
      (when (get-room-item rid 'fim) ;; quando chega em uma sala cujo valor de fim seja #t
        (begin
          (describe 'voce-venceu out) ;envia a mensagem de que o jogador venceu
          (exit))) ;;sai do jogo

      ;;imprime a descricao da sala e os itens disponiveis
      (when echo ;echo, definido no let é sempre true
        (write-line (format "--<([  ~a  ])>--" (get-room-description rid)) out) ;informa a descricao da sala
        (map (lambda (x) (describe x out)) (get-available-items rid))) ;mostra a descricao dos itens

      ;quando a vida do jogador é igual ou menor que 0, sai do loop e envia a mensagem que o jogador morreu
      (when (<= (player-attribute 'vida pid) 0) ;quando a vida do jogador é <= 0,
        (begin
          (describe 'jogador-morreu out) ;envia a mensagem que o jogador morreu
          (exit))) ;;sai do jogo

      ;;imprime todos os comandos disponiveis
      (print-available-commands rid out)
      (display (format "> ") out)

      ;;le um caractere, converte em uma string, depois em caixa baixa e depois converte novamente para simbolo
      (let ((input (string->symbol (string-downcase (symbol->string (read in))))))

        ;; se o comando for quit, sai do loop
        (if (eq? input 'quit) (exit) 'continue)

        ;verifica se o comando esta nas direcoes disponiveis
        (if (member input (get-available-directions rid)) ;;se input é membro da lista contendo as possiveis direcoes
            (let ((direction (lookup directions rid input))) ;;verifica a proxima sala
              (if (zero? direction) ; se a proxima sala for igual a zero, 
                  (loop rid #f) ;;faz o loop novamente com o echo como false para não repetir novamente o mesmo comando

                  ;; não permite que o jogador se mova para fora de uma sala caso haja um inimigo nela
                  (if (get-room-item rid 'inimigo)
                      (begin
                        (describe 'alerta-inimigo out) ;;envia a mensagem de que nao pode sair da sala com o inimigo nela
                        (loop rid #f)) ;;chama o loop novamente mas nao repete a descricao da sala

                      ;;checa se o quarto de destino esta trancado
                      (if (get-room-item direction 'trancado) ;verifica o valor de trancado no quarto indicado pelo numero contido em direction
                          (begin
                            (describe 'trancado out) ;;caso esteja trancado, envia a mensagem de que esta trancado
                            (loop rid #f)) ;;chama o loop novamente com echo false

                          ;;se nao esta trancado, vai para a sala destino
                          (loop direction #t))))) ;chama o loop novamente com a nova sala em direction e com o echo #t para receber a descricao da sala

          ;; verifica se o comando esta na lista de comandos possiveis
            ;;metodo so sera chamado se nao for comando de direcao, nem comando de sair do jogo
            (if (member input (get-available-commands rid))
                (begin
                  (process-command input rid out pid) ;caso esteja, chama o process-comand com o comando indicado
                  (loop rid #f)) ;;chama o loop novamente sem a descricao das salas

                ;;mostra uma mensagem caso o comando nao seja verdadeiro
                (begin
                  (write-line (format " ~a nao e um comando valido!" input) out)
                  (loop rid #f)))))))) ;;chama o loop novamente com echo false




